new function(_)
{
	var exec = new base2.Package(this, {
		name: "exec",
		parent: parchment,
		imports: "fatal, lang, parchment, parchment.beret, parchment.gnusto, parchment.library, parchment.runner, parchment.webZui",
		exports: "processBase64Zcode, _webZuiStartup" 
	});

	eval(this.imports);

	FatalError.prototype.onError = function(e) {
	  var message = e.message;
	  if (typeof e.message == "string")
	    message = message.entityify();
	  $("#content").append('<div class="error">An error occurred:<br/>' +
	                       '<pre>' + message + '\n\n' + e.traceback +
	                       '</pre></div>');
	}

	var library = new Library();
	window.library = library;

	function _webZuiStartup() {
	  var logfunc = function() {};

		// Setup the Firebug console
		if (window.loadFirebugConsole)
			window.loadFirebugConsole();
		if (window.console)
			logfunc = function(msg) { window.console.log(msg); };

	  var engine = new GnustoEngine(logfunc);
	  var zui = new WebZui(library, logfunc);
	  var runner = new EngineRunner(engine, zui, logfunc);
	  var beret = new Beret(engine);
		library.engine = engine;
		library.zui = zui;

	  beret.load(gZcode.slice());
	  logfunc("Story type: " + beret.m_filetype);
	  if (window.location.hash) {
	    if (window.location.hash.slice(1, 8) == "restart") {
	      window.location.hash = window.location.hash.slice(8);
	      zui._expectedHash = window.location.hash;
	    } else {
	      var b64data = window.location.hash.slice(1);
	      beret.load(decode_base64(b64data));
	    }
	    logfunc("Load game story type: " + beret.m_filetype);
	  }

	  runner.run();
	}

	function processZcodeAppspotResponse(content) {
	  if (content.error)
	    throw new FatalError("Error loading story: " + content.error.entityify());
	  processBase64Zcode(content.data);
	}

	function processBase64Zcode(data, decodedSoFar) {
	  var CHUNK_SIZE = 50000;

	  var firstChunk = data.slice(0, CHUNK_SIZE);
	  var restOfData = data.slice(CHUNK_SIZE);

	  if (typeof(decodedSoFar) == "undefined")
	    decodedSoFar = [];

	  $("#progress-text").html("Decoding " + data.length +
	                           " more bytes...");
	  decode_base64(firstChunk, decodedSoFar);

	  var next_func;

	  if (restOfData)
	    next_func = function decode_rest() {
	      processBase64Zcode(restOfData, decodedSoFar);
	    };
	  else
	    next_func = function finish() {
	      gZcode = decodedSoFar;
	      $("#progress-text").html("Starting interpreter...");
	      _webZuiStartup();
	    };

	  window.setTimeout(next_func, 10);
	}

	var gThisUrl = location.protocol + "//" + location.host + location.pathname;
	var gBaseUrl = gThisUrl.slice(0, gThisUrl.lastIndexOf("/"));
	var gZcode = null;

	var IF_ARCHIVE_PREFIX = "if-archive/";
	var ZCODE_APPSPOT_URL = "http://zcode.appspot.com/";

	function getFilenameFromUrl(url) {
	  var lastSlash = url.lastIndexOf("/");
	  return url.slice(lastSlash + 1);
	}

	$(document).ready(function() {
	  var qs = new Querystring();
	  var story = qs.get("story", "stories/troll.z5.js");
	  var storyName = getFilenameFromUrl(story);

	  storyName = storyName ? storyName + " - Parchment" : "Parchment";
	  window.document.title = storyName;

	  $("#progress-text").html("Retrieving story file...");

	  gStory = story;
	  if (story.slice(-3).toLowerCase() == ".js")
	    jQuery.getScript(story);
	  else
	    jQuery.getScript(ZCODE_APPSPOT_URL + "?url=" + escape(story) +
	                     "&jsonp=processZcodeAppspotResponse");
	});

	eval(this.exports);
};

var processBase64Zcode = parchment.exec.processBase64Zcode;
